<template>
  <el-dialog
    title="编辑公式"
    :visible="visible"
    width="1200px"
    :before-close="closeForm"
    :close-on-click-modal="false"
    :append-to-body="true"
    :destroy-on-close="true"
  >
    <div class="vue-formula">
      <div class="formula">
        <codemirror v-model="code" :options="options" @ready="onCmReady" />
      </div>
      <div v-if="validInfo" class="error">
        <span>公式错误：{{ validInfo }}</span>
      </div>
      <el-row :gutter="24" class="opt">
        <el-col :span="7">
          <fieldVariable
            :field-list="fields"
            @chiose="chioseField"
          />
        </el-col>
        <el-col :span="17">
          <funcVariable
            :nodes="funcList"
            @chiose="chioseFunc"
          />
        </el-col>
      </el-row>
    </div>
    <el-row slot="footer" style="text-align: center; margin-top: 20px">
      <el-button @click="reset">重 置</el-button>
      <el-button type="primary" @click="save">保 存</el-button>
    </el-row>
  </el-dialog>
</template>

<script>
import { codemirror } from 'vue-codemirror'
import FormulaEditorCore from './code/index'
import '../../config/codemirror'
import fieldVariable from './components/fieldVariable'
import funcVariable from './components/funcVariable'
import { funcList } from './code/funcList'
export default {
  components: {
    codemirror,
    fieldVariable,
    funcVariable
  },
  props: {
    formula: {
      type: Object,
      default: null
    },
    fieldList: {
      type: Array,
      default: () => []
    },
    visible: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      funcList,
      editorCore: null,
      code: '',
      func: {},
      fields: [],
      currentMenuId: null,
      validInfo: null,
      fieldCache: [],
      options: {
        autofocus: true,
        line: true,
        readOnly: false,
        dragDrop: false,
        height: '100px',
        theme: '3024-day', // 主题
        tabSize: 4, // 制表符的宽度
        autorefresh: false,
        smartIndent: true, // 上下文缩进
        lineNumbers: false, // 是否显示行号
        styleActiveLine: true, // 高亮选中行
        showCursorWhenSelecting: true // 当选择处于活动状态时是否应绘制游标
      }
    }
  },
  computed: {},
  watch: {
    code(val) {
      if (!val) {
        this.validInfo = null
        return
      }
      const { error, message } = this.editorCore.validateFormula(
        this.fieldCache
      )
      this.validInfo = error ? message : ''
    },
    fieldList: {
      handler(val) {
        if (val) {
          this.resetField()
        } else {
          this.fields = []
        }
      },
      immediate: true
    }
  },
  mounted() {},
  methods: {
    closeForm() {
      this.$emit('update:visible', false)
    },
    resetField() {
      const list = this.fieldList.map(c => {
        const t = {
          enCode: c.Id,
          label: c.Title,
          tableId: c.Id,
          type: 'table',
          disabled: true
        }
        if (c.Columns && c.Columns.length !== 0) {
          t.children = this.format(c, t)
        }
        return t
      })
      this.fields = list
    },
    format(sour, prt) {
      return sour.Columns.map(c => {
        const t = {
          enCode: c.ColId,
          label: c.ColTitle,
          tableId: prt.tableId,
          type: 'column',
          disabled: false
        }
        if (c.Children && c.Children.length !== 0) {
          t.type = 'group'
          t.disabled = true
          t.children = this.format(c, t)
        } else {
          t.DataType = c.DataType
          this.fieldCache.push(t)
          if (prt.type === 'group') {
            t.label = prt.label + '-' + c.ColTitle
          }
        }
        return t
      })
    },
    chioseFunc(formula) {
      this.editorCore.insertText(`${formula.name}()`, 'formula', formula.isNullParam)
    },
    onCmReady(codemirror) {
      this.editorCore = new FormulaEditorCore(codemirror, funcList)
      this.editorCore.registerListen()
      if (this.formula != null) {
        const data = {
          text: this.formula.Formula,
          marks: this.formula.VarCol.map(c => {
            return {
              enCode: c.ColId,
              menuId: c.MenuId,
              from: {
                ch: c.From.Ch,
                line: c.From.Line,
                sticky: c.From.Sticky
              },
              to: {
                ch: c.To.Ch,
                line: c.To.Line,
                sticky: c.To.Sticky
              }
            }
          })
        }
        this.editorCore.renderData(data)
      } else {
        this.reset()
      }
    },
    reset() {
      this.code = ''
      this.editorCore.reset()
    },
    drop() {
      this.editorCore.delete()
    },
    save() {
      const data = this.editorCore.getData()
      if (data == null) {
        this.$emit('save', null)
      } else {
        const text = data.text
        const vars = data.marks.map(c => {
          const t = this.fieldCache.find(a => a.enCode === c.enCode)
          return {
            ColId: t.enCode,
            TableId: t.tableId,
            MenuId: c.menuId,
            From: {
              Ch: c.from.ch,
              Line: c.from.line,
              Sticky: c.from.sticky
            },
            To: {
              Ch: c.to.ch,
              Line: c.to.line,
              Sticky: c.to.sticky
            }
          }
        })
        const res = {
          Formula: text,
          VarCol: vars
        }
        this.$emit('save', res)
      }
      this.$emit('update:visible', false)
    },
    chioseField(field) {
      this.editorCore.insertText(
        {
          ...field,
          menuId: this.currentMenuId
        },
        'field'
      )
    }
  }
}
</script>

<style scoped>
.vue-formula {
   width: 100%;
}
.vue-formula .formula {
  height: 105px;
  border: 1px solid #9093997d;
}
.vue-formula .formula .optBtn {
  height: 25px;
  line-height: 25px;
  margin-bottom: 10px;
  text-align: right;
}
.vue-formula .error {
  padding: 0 6px;
  color: #8d3030;
  height: 30px;
  line-height: 30px;
}
.vue-formula .opt {
  min-height: 300px;
  margin-top: 10px;
}
</style>

<style>
.vue-formula .CodeMirror {
  height: 100px;
}
.dark .vue-formula .CodeMirror {
  background-color: #1d1e1f;
  color: #fff;
}
.CodeMirror-hints {
  z-index: 30000 !important;
  background-color: #f0f0f0;
  color: #333;
  width: 130px;
  font-size: 14px;
  border: 1px solid #ccc;
  padding: 10px;
  border-radius: 4px;
  max-height: 100px;
  overflow-y: auto;
}
.cm-string {
  color: #f56c6c !important;
}
.cm-field {
  color: #2f7deb !important;
  border-radius: 2px;
  display: inline-block;
  font-size: 14px;
  margin: 0 2px;
  padding: 3px 5px;
}
</style>
